﻿using Dungen;
using HarmonyLib;
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Text;
using UnityEngine;
using static AIAct;
using static System.Collections.Generic.List<Thing>;
using static UnityEngine.GraphicsBuffer;

namespace Erika;

public class OnSteal
{
    [HarmonyPatch(typeof(AIAct), "Do")]
    [HarmonyPrefix]
    public static bool BeforeStealDo(AIAct __instance, ref AIAct _seq)
    {
        if (__instance is AI_Steal)
        {
            //Plugin.LogInfo("Act is AI_Steal");
            var stealAct = __instance as AI_Steal;

            Chara chara = Act.TC.Chara; // hack: the steal action will change target on Run(), so we should us Act.TC
            ICardParent targetParent = stealAct.target.parent;
            Card tg = chara;
            if (tg == null)
            {
                tg = stealAct.target;
            }

            Card root = tg.GetRootCard();

            _seq = new Progress_Custom
            {
                canProgress = () => stealAct.target.parent == targetParent,
                onProgressBegin = delegate
                {
                },
                onProgress = delegate (Progress_Custom p)
                {
                    stealAct.owner.LookAt(root);
                    stealAct.owner.PlaySound("steal");
                    root.renderer.PlayAnime(AnimeID.Shiver);

                    //Plugin.LogInfo(stealAct.owner.NameSimple + "  AI_Steal onProgress" + " chara " + (chara != null) + "  hasChara " + (stealAct.target.Chara != null));
                    //Plugin.LogInfo("tr.isChara  " + stealAct.target.isChara + "  trname " + stealAct.target.NameSimple);
                    //if (tg == stealAct.target)
                    //    Plugin.LogInfo("tg == stealAct.target");
                    //if (chara != null)
                    //    Plugin.LogInfo("" + chara.NameSimple + "tc chara AI_Steal dist " + stealAct.owner.Dist(chara));

                    if (chara != null && stealAct.owner.Dist(chara) > 1)
                    {
                        //Plugin.LogInfo("tc chara AI_Steal dist " + stealAct.owner.Dist(chara));
                        stealAct.owner.TryMoveTowards(chara.pos);
                        if (stealAct.owner == null)
                        {
                            p.Cancel();
                            return;
                        }

                        if (chara != null && stealAct.owner.Dist(chara) > 1 || !chara.ExistsOnMap)
                        {
                            //Plugin.LogInfo("tc dist to far" + stealAct.owner.Dist(chara));

                            EClass.pc.Say("targetTooFar");
                            p.Cancel();
                            return;
                        }
                    }

                    if (stealAct.target.ChildrenAndSelfWeight > stealAct.owner.Evalue(281) * 200 + stealAct.owner.STR * 100 + 1000)
                    {
                        EClass.pc.Say("tooHeavy", stealAct.target);
                        p.Cancel();
                    }
                    else if (stealAct.owner.pos.TryWitnessCrime(stealAct.owner, null, 4, delegate (Chara c)
                    {
                        int num = ((!c.CanSeeInvisible(stealAct.owner)) ? 30 : 0);
                        int num2 = c.PER * 250 / 100;
                        if (c == chara && stealAct.target.Thing != null && stealAct.target.Thing.isEquipped)
                        {
                            num2 *= 3;
                        }

                        return EClass.rnd(num2) > stealAct.owner.Evalue(281) + stealAct.owner.DEX + num;
                    }))
                    {
                        p.Cancel();
                    }
                    else
                    {
                        int count = stealAct.owner.pos.ListWitnesses(stealAct.owner).Count;
                        stealAct.owner.elements.ModExp(281, Mathf.Min(count * 5 + 5, 25));
                    }
                },
                onProgressComplete = delegate
                {
                    if (stealAct.target.isThing && stealAct.target.IsInstalled)
                    {
                        stealAct.target.SetPlaceState(PlaceState.roaming);
                    }

                    stealAct.owner.Say("steal_end", stealAct.owner, stealAct.target);
                    if (chara != null && (chara.IsPCFaction || chara.OriginalHostility >= Hostility.Friend))
                    {
                        EClass.player.ModKarma(-2);
                    }
                    //else if (EClass.rnd(2) == 0)
                    //{
                    //    EClass.player.ModKarma(-1);
                    //}

                    stealAct.target.isNPCProperty = false;
                    stealAct.owner.Pick(stealAct.target.Thing);
                    stealAct.owner.elements.ModExp(281, 50);

                    float spCost = 0;
                    spCost += (float)stealAct.target.SelfWeight / ((Act.CC.STR * 3f + Act.CC.DEX * 6f + stealAct.owner.Evalue(281) * 6f) * 100f);
                    var costint = (int)Math.Floor(spCost);
                    stealAct.owner.stamina.Mod(-costint);
                    spCost -= costint;
                    if (EClass.rndf(1) < spCost)
                    {
                        stealAct.owner.stamina.Mod(-1);
                    }
                }
            }.SetDuration(20, 4);

        }

        return true;
    }

    [HarmonyPatch(typeof(ThingContainer), "FindStealable")]
    [HarmonyPrefix]
    public static bool AfterSteal(ThingContainer __instance, ref Thing __result)
    {
        var stealSkill = Act.CC.elements.GetOrCreateElement(281).Value;
        if (Act.CC != EClass.pc)
        {
            stealSkill = 0;
        }

        using (Enumerator enumerator = __instance.GetEnumerator())
        {
            while (enumerator.MoveNext())
            {
                Thing current = enumerator.Current;
                //if (current.isEquipped && (stealSkill < (current.SelfWeight / 100) || Act.CC.STR < (current.SelfWeight / 1000) || Act.CC.DEX < __instance.owner.PER))
                //{
                //    continue;
                //}
                if (current.IsContainer)
                {
                    continue;
                }

                __result = current;
                return false;
            }
        }
        __result = null;

        return false;
    }
}
